在講閉包前,先補充一點執行環境的東西。
之前講到當一個執行環境產生時,會建立自己的區域變數,
會建立一個叫作Activation object(找不到中文翻譯 執行中物件?)的物件,
裡面除了有區域變數跟函式外,還有參數跟引數。
所以一個函式執行環境內,大概會有這些東西
好了回到閉包,一樣先來看維基對閉包的介紹
在電腦科學中,閉包(英語:Closure),又稱詞法閉包(Lexical Closure)或函式閉包(function closures),是在支援頭等函式的程式語言中實現詞法繫結的一種技術。閉包在實現上是一個結構體,它儲存了一個函式(通常是其入口位址)和一個關聯的環境(相當於一個符號尋找表)。環境裡是若干對符號和值的對應關係,它既要包括約束變數(該函式內部繫結的符號),也要包括自由變數(在函式外部定義但在函式內被參照),有些函式也可能沒有自由變數。閉包跟函式最大的不同在於,當捕捉閉包的時候,它的自由變數會在捕捉時被確定,這樣即便脫離了捕捉時的上下文,它也能照常執行。
......
還是來看程式吧
var a = '全域變數';
function makeFunc() {
var a = '區域變數';
return function () {
return a;
};
}
var func = makeFunc();
console.log(func());
makeFunc
會宣告一個函式(return a)後回傳,
將makeFunc
回傳的函式給func
,這時後印出呼叫func
回傳的結果(a),
照範圍鍊來看,a應該參照到makeFunc
內的區域變數a,
但makeFunc
的執行環境早已消滅,區域變數應該都被消去了,此時"理論"上會參照到全域變數a
像這樣
但是實際的結果makeFunc
都消滅了區域變數a卻還在,這是為什麼呢?
其實當makeFunc
內的函式被宣告時,會記住範圍鍊上的區域變數,
即使原本區域變數的執行環境消滅,只要這個函式還在就能存取到a變數。
像這樣子,區域變數a被保留著,此時此變數a只有func
函式可以訪問得到,沒辦法用其他方式存取
講那麼多,所以閉包到底是甚麼?